1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import com.google.common.annotations.GwtCompatible;
20  
21  import java.util.Collection;
22  import java.util.Comparator;
23  import java.util.Map.Entry;
24  
25  import javax.annotation.Nullable;
26  
27  /**
28   * An immutable {@link ListMultimap} with reliable user-specified key and value
29   * iteration order. Does not permit null keys or values.
30   *
31   * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is
32   * a <i>view</i> of a separate multimap which can still change, an instance of
33   * {@code ImmutableListMultimap} contains its own data and will <i>never</i>
34   * change. {@code ImmutableListMultimap} is convenient for
35   * {@code public static final} multimaps ("constant multimaps") and also lets
36   * you easily make a "defensive copy" of a multimap provided to your class by
37   * a caller.
38   *
39   * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
40   * it has no public or protected constructors. Thus, instances of this class
41   * are guaranteed to be immutable.
42   *
43   * <p>See the Guava User Guide article on <a href=
44   * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
45   * immutable collections</a>.
46   *
47   * @author Jared Levy
48   * @since 2.0 (imported from Google Collections Library)
49   */
50  @GwtCompatible(serializable = true, emulated = true)
51  public class ImmutableListMultimap<K, V>
52      extends ImmutableMultimap<K, V>
53      implements ListMultimap<K, V> {
54  
55    /** Returns the empty multimap. */
56    // Casting is safe because the multimap will never hold any elements.
57    @SuppressWarnings("unchecked")
58    public static <K, V> ImmutableListMultimap<K, V> of() {
59      return (ImmutableListMultimap<K, V>) EmptyImmutableListMultimap.INSTANCE;
60    }
61  
62    /**
63     * Returns an immutable multimap containing a single entry.
64     */
65    public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) {
66      ImmutableListMultimap.Builder<K, V> builder
67          = ImmutableListMultimap.builder();
68      builder.put(k1, v1);
69      return builder.build();
70    }
71  
72    /**
73     * Returns an immutable multimap containing the given entries, in order.
74     */
75    public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) {
76      ImmutableListMultimap.Builder<K, V> builder
77          = ImmutableListMultimap.builder();
78      builder.put(k1, v1);
79      builder.put(k2, v2);
80      return builder.build();
81    }
82  
83    /**
84     * Returns an immutable multimap containing the given entries, in order.
85     */
86    public static <K, V> ImmutableListMultimap<K, V> of(
87        K k1, V v1, K k2, V v2, K k3, V v3) {
88      ImmutableListMultimap.Builder<K, V> builder
89          = ImmutableListMultimap.builder();
90      builder.put(k1, v1);
91      builder.put(k2, v2);
92      builder.put(k3, v3);
93      return builder.build();
94    }
95  
96    /**
97     * Returns an immutable multimap containing the given entries, in order.
98     */
99    public static <K, V> ImmutableListMultimap<K, V> of(
100       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
101     ImmutableListMultimap.Builder<K, V> builder
102         = ImmutableListMultimap.builder();
103     builder.put(k1, v1);
104     builder.put(k2, v2);
105     builder.put(k3, v3);
106     builder.put(k4, v4);
107     return builder.build();
108   }
109 
110   /**
111    * Returns an immutable multimap containing the given entries, in order.
112    */
113   public static <K, V> ImmutableListMultimap<K, V> of(
114       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
115     ImmutableListMultimap.Builder<K, V> builder
116         = ImmutableListMultimap.builder();
117     builder.put(k1, v1);
118     builder.put(k2, v2);
119     builder.put(k3, v3);
120     builder.put(k4, v4);
121     builder.put(k5, v5);
122     return builder.build();
123   }
124 
125   // looking for of() with > 5 entries? Use the builder instead.
126 
127   /**
128    * Returns a new builder. The generated builder is equivalent to the builder
129    * created by the {@link Builder} constructor.
130    */
131   public static <K, V> Builder<K, V> builder() {
132     return new Builder<K, V>();
133   }
134 
135   /**
136    * A builder for creating immutable {@code ListMultimap} instances, especially
137    * {@code public static final} multimaps ("constant multimaps"). Example:
138    * <pre>   {@code
139    *
140    *   static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP =
141    *       new ImmutableListMultimap.Builder<String, Integer>()
142    *           .put("one", 1)
143    *           .putAll("several", 1, 2, 3)
144    *           .putAll("many", 1, 2, 3, 4, 5)
145    *           .build();}</pre>
146    *
147    * <p>Builder instances can be reused; it is safe to call {@link #build} multiple
148    * times to build multiple multimaps in series. Each multimap contains the
149    * key-value mappings in the previously created multimaps.
150    *
151    * @since 2.0 (imported from Google Collections Library)
152    */
153   public static final class Builder<K, V>
154       extends ImmutableMultimap.Builder<K, V> {
155     /**
156      * Creates a new builder. The returned builder is equivalent to the builder
157      * generated by {@link ImmutableListMultimap#builder}.
158      */
159     public Builder() {}
160 
161     @Override public Builder<K, V> put(K key, V value) {
162       super.put(key, value);
163       return this;
164     }
165 
166     /**
167      * {@inheritDoc}
168      *
169      * @since 11.0
170      */
171     @Override public Builder<K, V> put(
172         Entry<? extends K, ? extends V> entry) {
173       super.put(entry);
174       return this;
175     }
176 
177     @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
178       super.putAll(key, values);
179       return this;
180     }
181 
182     @Override public Builder<K, V> putAll(K key, V... values) {
183       super.putAll(key, values);
184       return this;
185     }
186 
187     @Override public Builder<K, V> putAll(
188         Multimap<? extends K, ? extends V> multimap) {
189       super.putAll(multimap);
190       return this;
191     }
192 
193     /**
194      * {@inheritDoc}
195      *
196      * @since 8.0
197      */
198     @Override
199     public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
200       super.orderKeysBy(keyComparator);
201       return this;
202     }
203 
204     /**
205      * {@inheritDoc}
206      *
207      * @since 8.0
208      */
209     @Override
210     public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
211       super.orderValuesBy(valueComparator);
212       return this;
213     }
214 
215     /**
216      * Returns a newly-created immutable list multimap.
217      */
218     @Override public ImmutableListMultimap<K, V> build() {
219       return (ImmutableListMultimap<K, V>) super.build();
220     }
221   }
222 
223   /**
224    * Returns an immutable multimap containing the same mappings as {@code
225    * multimap}. The generated multimap's key and value orderings correspond to
226    * the iteration ordering of the {@code multimap.asMap()} view.
227    *
228    * <p>Despite the method name, this method attempts to avoid actually copying
229    * the data when it is safe to do so. The exact circumstances under which a
230    * copy will or will not be performed are undocumented and subject to change.
231    *
232    * @throws NullPointerException if any key or value in {@code multimap} is
233    *         null
234    */
235   public static <K, V> ImmutableListMultimap<K, V> copyOf(
236       Multimap<? extends K, ? extends V> multimap) {
237     if (multimap.isEmpty()) {
238       return of();
239     }
240 
241     // TODO(user): copy ImmutableSetMultimap by using asList() on the sets
242     if (multimap instanceof ImmutableListMultimap) {
243       @SuppressWarnings("unchecked") // safe since multimap is not writable
244       ImmutableListMultimap<K, V> kvMultimap
245           = (ImmutableListMultimap<K, V>) multimap;
246       if (!kvMultimap.isPartialView()) {
247         return kvMultimap;
248       }
249     }
250 
251     ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder();
252     int size = 0;
253 
254     for (Entry<? extends K, ? extends Collection<? extends V>> entry
255         : multimap.asMap().entrySet()) {
256       ImmutableList<V> list = ImmutableList.copyOf(entry.getValue());
257       if (!list.isEmpty()) {
258         builder.put(entry.getKey(), list);
259         size += list.size();
260       }
261     }
262 
263     return new ImmutableListMultimap<K, V>(builder.build(), size);
264   }
265 
266   ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) {
267     super(map, size);
268   }
269 
270   // views
271 
272   /**
273    * Returns an immutable list of the values for the given key.  If no mappings
274    * in the multimap have the provided key, an empty immutable list is
275    * returned. The values are in the same order as the parameters used to build
276    * this multimap.
277    */
278   @Override public ImmutableList<V> get(@Nullable K key) {
279     // This cast is safe as its type is known in constructor.
280     ImmutableList<V> list = (ImmutableList<V>) map.get(key);
281     return (list == null) ? ImmutableList.<V>of() : list;
282   }
283 
284   private transient ImmutableListMultimap<V, K> inverse;
285 
286   /**
287    * {@inheritDoc}
288    *
289    * <p>Because an inverse of a list multimap can contain multiple pairs with
290    * the same key and value, this method returns an {@code
291    * ImmutableListMultimap} rather than the {@code ImmutableMultimap} specified
292    * in the {@code ImmutableMultimap} class.
293    *
294    * @since 11.0
295    */
296   @Override
297   public ImmutableListMultimap<V, K> inverse() {
298     ImmutableListMultimap<V, K> result = inverse;
299     return (result == null) ? (inverse = invert()) : result;
300   }
301 
302   private ImmutableListMultimap<V, K> invert() {
303     Builder<V, K> builder = builder();
304     for (Entry<K, V> entry : entries()) {
305       builder.put(entry.getValue(), entry.getKey());
306     }
307     ImmutableListMultimap<V, K> invertedMultimap = builder.build();
308     invertedMultimap.inverse = this;
309     return invertedMultimap;
310   }
311 
312   /**
313    * Guaranteed to throw an exception and leave the multimap unmodified.
314    *
315    * @throws UnsupportedOperationException always
316    * @deprecated Unsupported operation.
317    */
318   @Deprecated @Override public ImmutableList<V> removeAll(Object key) {
319     throw new UnsupportedOperationException();
320   }
321 
322   /**
323    * Guaranteed to throw an exception and leave the multimap unmodified.
324    *
325    * @throws UnsupportedOperationException always
326    * @deprecated Unsupported operation.
327    */
328   @Deprecated @Override public ImmutableList<V> replaceValues(
329       K key, Iterable<? extends V> values) {
330     throw new UnsupportedOperationException();
331   }
332 }